﻿using System;
using System.Reflection;
using Net.Share;

namespace Net.Adapter
{
    /// <summary>
    /// 远程过程调用适配器
    /// </summary>
    public class CallSiteRpcAdapter : NormalRpcAdapter
    {
        /// <summary>
        /// 构造客户端Rpc适配器，参数是xxxClient对象
        /// </summary>
        /// <param name="logRpc"></param>
        public CallSiteRpcAdapter(bool logRpc = false)
        {
            LogRpc = logRpc;
        }

        public override IRpcAdapter Copy()
        {
            return new CallSiteRpcAdapter() { LogRpc = LogRpc, Mode = Mode };
        }

        public override void AddRpc(object target, AddRpcMode mode = AddRpcMode.None, Action<SyncVarInfo> onSyncVarCollect = null)
        {
            var type = target.GetType();
            AddRpc(target, type, mode, onSyncVarCollect, (info, member) =>
            {
                var method = info as MethodInfo;
                Type[] parmsTypes;
                Type genericType;
                if (method.ReturnType != typeof(void))
                {
                    var pars = method.GetParameters();
                    parmsTypes = new Type[pars.Length + 1];
                    for (var i = 0; i < pars.Length; i++)
                        parmsTypes[i] = pars[i].ParameterType;
                    parmsTypes[pars.Length] = method.ReturnType;
                    genericType = Type.GetType($"Net.Adapter.RpcFuncPtr`{pars.Length + 1}");
                    if (genericType == null)
                        throw new Exception($"找不到方法:{method}, 请点击unity菜单GameDesigner/Network/GenerateRpcHook生成!");
                    genericType = genericType.MakeGenericType(parmsTypes);
                }
                else
                {
                    var pars = method.GetParameters();
                    parmsTypes = new Type[pars.Length];
                    for (var i = 0; i < pars.Length; i++)
                        parmsTypes[i] = pars[i].ParameterType;
                    genericType = typeof(RpcMethodPtrNull);
                    if (parmsTypes.Length > 0)
                    {
                        genericType = Type.GetType($"Net.Adapter.RpcMethodPtr`{pars.Length}");
                        if (genericType == null)
                            throw new Exception($"找不到方法:{method}, 请点击unity菜单GameDesigner/Network/GenerateRpcHook生成!");
                        genericType = genericType.MakeGenericType(parmsTypes);
                    }
                }
                var rpcMethodPtr = (RpcMethodPtr)Activator.CreateInstance(genericType);
                rpcMethodPtr.cmd = member.rpc.cmd;
                rpcMethodPtr.method = method;
                member.ptr = rpcMethodPtr;
            },
            (member) =>
            {
                var rpcMethodPtr = member.ptr.Clone(target); //每次收集都要重新创建, 否则只会指向第一个创建委托对象的target
                return new RPCMethodPtr(target, member.member as MethodInfo, member.rpc.cmd, rpcMethodPtr);
            });
        }
    }
}